;;; GNU Guix --- Functional package management for GNU
;;;
;;; Copyright © 2022 (unmatched parenthesis <paren@disroot.org>
;;;
;;; This file is not part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

;;; Attribution for the tree-sitter packages: https://issues.guix.gnu.org/49946

(define-module (guixrus packages tree-sitter)
  #:use-module (guix build-system cargo)
  #:use-module (guix download)
  #:use-module ((guix licenses) #:prefix license:)
  #:use-module (guix packages)
  #:use-module (guix utils)
  #:use-module (gnu packages crates-graphics)
  #:use-module (gnu packages crates-io)
  #:use-module (gnu packages text-editors)
  #:use-module ((guixrus packages common rust) #:prefix rus:))

(define-public rust-tree-sitter-0.20
  (package
    (name "rust-tree-sitter")
    (version "0.20.6")
    (source
      (origin
        (method url-fetch)
        (uri (crate-uri "tree-sitter" version))
        (file-name (string-append name "-" version ".tar.gz"))
        (sha256
          (base32 "0wcvxgnvj7ga1y7xa7wm0pmabkfj8936ifg8jacd4201cj0vgcq9"))))
    (build-system cargo-build-system)
    (arguments
      `(#:skip-build?
        #t
        #:cargo-inputs
        (("rust-cc" ,rust-cc-1)
         ("rust-lazy-static" ,rust-lazy-static-1)
         ("rust-regex" ,rust-regex-1))))
    (home-page "https://github.com/tree-sitter/tree-sitter")
    (synopsis "Rust bindings to the Tree-sitter parsing library")
    (description "Rust bindings to the Tree-sitter parsing library")
    (license license:expat)))

(define-public tree-sitter-cli
  (package (inherit tree-sitter)
    (name "tree-sitter-cli")
    (build-system cargo-build-system)
    (arguments
     `(;; Running test requires downloading fixtures, see the
       ;; script/fetch-fixtures script.
       #:tests? #f
       ;; FIXME: Installing the sources for the tree-sitter Rust bindings
       ;; doesn't work out of the box due to tree-sitter having multiple
       ;; Rust packages in the same repository (bindings and CLI).
       #:install-source? #f
       #:cargo-inputs
       (("rust-ansi-term" ,rust-ansi-term-0.12)
        ("rust-anyhow" ,rust-anyhow-1)
        ("rust-atty" ,rust-atty-0.2)
        ("rust-cc" ,rust-cc-1)
        ("rust-clap" ,rust-clap-2)
        ("rust-difference" ,rust-difference-2)
        ("rust-dirs" ,rust-dirs-3)
        ("rust-glob" ,rust-glob-0.3)
        ("rust-html-escape" ,rus:rust-html-escape-0.2)
        ("rust-lazy-static" ,rust-lazy-static-1)
        ("rust-libloading" ,rust-libloading-0.7)
        ("rust-log" ,rust-log-0.4)
        ("rust-memchr" ,rust-memchr-2)
        ("rust-once-cell" ,rust-once-cell-1)
        ("rust-regex" ,rust-regex-1)
        ("rust-regex-syntax" ,rust-regex-syntax-0.6)
        ("rust-rustc-hash" ,rust-rustc-hash-1)
        ("rust-semver" ,rust-semver-1)
        ("rust-serde" ,rust-serde-1)
        ("rust-serde-json" ,rust-serde-json-1)
        ("rust-smallbitvec" ,rus:rust-smallbitvec-2)
        ("rust-thiserror" ,rust-thiserror-1)
        ("rust-tiny-http" ,rust-tiny-http-0.8)
        ("rust-toml" ,rust-toml-0.5)
        ("rust-walkdir" ,rust-walkdir-2)
        ("rust-webbrowser" ,rust-webbrowser-0.5)
        ("rust-which" ,rust-which-4))
       #:cargo-development-inputs
       (("rust-ctor" ,rust-ctor-0.1)
        ("rust-pretty-assertions" ,rust-pretty-assertions-0.7)
        ("rust-rand" ,rust-rand-0.8)
        ("rust-tempfile" ,rust-tempfile-3))
       #:phases
       (modify-phases %standard-phases
         (add-after 'unpack 'delete-cargo.lock
           (lambda _ (delete-file "Cargo.lock")))
         (replace 'install
           (lambda* (#:key outputs #:allow-other-keys)
             (let* ((out (assoc-ref outputs "out"))
                    (bin (string-append out "/bin"))
                    (lib (string-append out "/lib")))
               (mkdir-p bin)
               (install-file "target/release/tree-sitter" bin)))))))
    (synopsis "Incremental parsing system for programming tools")
    (description "Tree-sitter is a parser generator tool and an incremental
parsing library.  It can build a concrete syntax tree for a source file and
efficiently update the syntax tree as the source file is edited.

Tree-sitter aims to be:

@enumerate
@item General enough to parse any programming language.
@item Fast enough to parse on every keystroke in a text editor.
@item Robust enough to provide useful results even in the presence of syntax
errors.
@item Dependency-free so that the runtime library (which is written in pure C)
can be embedded in any application.
@end enumerate

This package includes the @command{tree-sitter} command-line tool.")
    (license license:expat)))
